﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace AntsCode.StorageClientExtensions.Denormalization
{
    public class DenormalizationRules : IEnumerable<DenormalizationRule>
    {
        private Type sourceType;
        private List<DenormalizationRule> rules;

        public DenormalizationRules(Type sourceType)
        {
            this.sourceType = sourceType;
            this.rules = new List<DenormalizationRule>(); 
        }

        public void Add<TSource, TDestination>(
            Expression<Func<TSource, object>> source,
            Expression<Func<TDestination, object>> destination,
            Expression<Func<TSource, TDestination, bool>> filter,
            Expression<Func<TSource, TDestination, bool>> reverseFilter,
            bool runAsync,
            DenormalizedDelegate<TSource, TDestination> onDenormalized = null,
            DenormalizedDelegate<TSource, TDestination> onReverseDenormalized = null)
        {
            if (this.sourceType == null || typeof(TSource) == this.sourceType || typeof(TDestination) == this.sourceType)
            {
                rules.Add(new DenormalizationRule(
                    typeof(TSource),
                    typeof(TDestination),
                    new Expression<Func<TSource, object>>[] { source },
                    new Expression<Func<TDestination, object>>[] { destination },
                    filter,
                    reverseFilter,
                    runAsync,
                    onDenormalized,
                    onReverseDenormalized));
            }
        }

        public void Add<TSource, TDestination>(
            Expression<Func<TSource, object>>[] sources,
            Expression<Func<TDestination, object>>[] destinations,
            Expression<Func<TSource, TDestination, bool>> filter,
            Expression<Func<TSource, TDestination, bool>> reverseFilter,
            bool runAsync,
            DenormalizedDelegate<TSource, TDestination> onDenormalized = null,
            DenormalizedDelegate<TSource, TDestination> onReverseDenormalized = null)
        {
            if (this.sourceType == null || typeof(TSource) == this.sourceType || typeof(TDestination) == this.sourceType)
            {
                rules.Add(new DenormalizationRule(
                    typeof(TSource),
                    typeof(TDestination),
                    sources,
                    destinations,
                    filter,
                    reverseFilter,
                    runAsync,
                    onDenormalized,
                    onReverseDenormalized));
            }
        }

        #region IEnumerable<DenormalizationRule> Members

        public IEnumerator<DenormalizationRule> GetEnumerator()
        {
            return rules.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return rules.GetEnumerator();
        }

        #endregion
    }
}